package edu.cmpe283.prj2.manager;

import edu.cmpe283.prj2.dao.JdbcVmDao;
import edu.cmpe283.prj2.model.Axis;
import edu.cmpe283.prj2.model.ChartData;
import edu.cmpe283.prj2.model.HostInfo;
import edu.cmpe283.prj2.model.VmCPU;
import edu.cmpe283.prj2.model.VmDisk;
import edu.cmpe283.prj2.model.VmMemory;
import edu.cmpe283.prj2.model.VmNetwork;
import edu.cmpe283.prj2.model.VmProcess;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import java.util.*;


public class VmManager {


	@Qualifier("vmDao")
	@Autowired
	private JdbcVmDao vmDao;


	public Axis getVmCpu(String vmHostName , int rollupStamp) {
		
		
		
		

		List<VmCPU> l = vmDao.getCpu( vmHostName ,  rollupStamp);

		
		List<ChartData> ChartDataList = new ArrayList<ChartData>();
		for (int i =0 ; i <l.size() ; i++ )
		{
			System.out.println(l.get(i).getHostName());
			ChartData tempChartData = new ChartData();
			tempChartData.setDateTime(l.get(i).getDateTime());
			tempChartData.setHostName(l.get(i).getHostName());
			tempChartData.setValue(l.get(i).getcPUUsage());
			ChartDataList.add(tempChartData);
		}

		return convertToChartFormat(ChartDataList);
		
	}

	




	public Axis  getVmNetworkTx(String vmHostName , int rollupStamp)
	{
		
		
		
		List<VmNetwork> inputNetworkTxList = vmDao.getVmNetworkData(vmHostName ,  rollupStamp);
		
		List<ChartData> ChartDataList = new ArrayList<ChartData>();
		for (int i =0 ; i <inputNetworkTxList.size() ; i++ )
		{
			System.out.println(inputNetworkTxList.get(i).getHostName());
			ChartData tempChartData = new ChartData();
			tempChartData.setDateTime(inputNetworkTxList.get(i).getDateTime());
			tempChartData.setHostName(inputNetworkTxList.get(i).getHostName());
			tempChartData.setValue(inputNetworkTxList.get(i).getTx());
			ChartDataList.add(tempChartData);
		}

		return convertToChartFormat(ChartDataList);

		
		
	}






	
	public Axis  getVmProcessThreads(String vmHostName , int rollupStamp)
	{
		
		List<VmProcess> inputProcessList = vmDao.getVmProcessData(vmHostName ,  rollupStamp);
		
		//convert into chartAxis Pojo 
		
		List<ChartData> ChartDataList = new ArrayList<ChartData>();
		for (int i =0 ; i <inputProcessList.size() ; i++ )
		{
			ChartData tempChartData = new ChartData();
			tempChartData.setDateTime(inputProcessList.get(i).getDateTime());
			tempChartData.setHostName(inputProcessList.get(i).getHostName());
			tempChartData.setValue(inputProcessList.get(i).getThreads());
			ChartDataList.add(tempChartData);
		}

		return convertToChartFormat(ChartDataList);
		
		
	}
	
	
	public Axis  getVmNetworkRx(String vmHostName , int rollupStamp)
	{
		
		List<VmNetwork> inputNetworkRxList = vmDao.getVmNetworkData(vmHostName ,  rollupStamp);
		
		//convert into chartAxis Pojo 
		
		List<ChartData> ChartDataList = new ArrayList<ChartData>();
		for (int i =0 ; i <inputNetworkRxList.size() ; i++ )
		{
			ChartData tempChartData = new ChartData();
			tempChartData.setDateTime(inputNetworkRxList.get(i).getDateTime());
			tempChartData.setHostName(inputNetworkRxList.get(i).getHostName());
			tempChartData.setValue(inputNetworkRxList.get(i).getRx());
			ChartDataList.add(tempChartData);
		}

		return convertToChartFormat(ChartDataList);
		
		
	}

	private Axis convertToChartFormat(List<ChartData> ChartDataList) {
		
		
		Map<String, Map<Date ,Double > > hostValuemap = new HashMap<String, Map<Date ,Double >  >();
		
		Set<Date> timestampHashSet = new HashSet<Date>();
		
		for (int i =0 ; i <ChartDataList.size() ; i++ ){
			
			ChartData tempData = ChartDataList.get(i);
			
			
			timestampHashSet.add(tempData.getDateTime());
			
			String  tempVMHostName =tempData.getHostName();
					
			if(hostValuemap.containsKey(tempVMHostName)){
				hostValuemap.get(tempVMHostName).put(tempData.getDateTime(), tempData.getValue());
			} else {
				 Map<Date ,Double > timeValueMap = new HashMap<Date ,Double >();
				 timeValueMap.put(tempData.getDateTime(), tempData.getValue());
				hostValuemap.put(tempVMHostName, timeValueMap);
			}
			
			
		}
			List<Date> xAxis = new ArrayList<Date>(timestampHashSet);
			Collections.sort(xAxis);
			
			
			//check if timestamp data is missing  and form highchart output 
			
			
			String yaxisFormat =  "[";
			for (String hostName : hostValuemap.keySet())
			{
				yaxisFormat+= "{name: '"+ hostName + "' ,data: " + getCSV(hostValuemap.get(hostName) , xAxis) +" },";
			}

			yaxisFormat = yaxisFormat.substring(0, yaxisFormat.length()-1)+"]";
			
			
			System.out.println(xAxis);
			System.out.println(yaxisFormat);
			
			return new Axis(xAxis, yaxisFormat);
		
	}

	private String getCSV(Map<Date, Double> map , List xAxis) {
		
		String s = "[";
		
		for (int i =0 ; i < xAxis.size() ; i++)
		{
			if(map.containsKey(xAxis.get(i)))
			{
				s += map.get(xAxis.get(i)) + ",";
			}
			else
			{
				s += 0 + ",";
			}
		}
		
		s = s.substring(0, s.length()-1) + "]";
		
		
		return s;
		
		
	}

//Memory
	public Axis getVmMemoryData(String vmHostName , int rollupStamp) {

		List<VmMemory> l = vmDao.getVmMemoryData(vmHostName ,  rollupStamp);

		Map<String, List<VmMemory>> map = new HashMap<String, List<VmMemory>>();
		Set<Date> s = new HashSet<Date>();

		for (VmMemory VmMemory : l) {
			s.add(VmMemory.getDateTime());
			if(map.containsKey(VmMemory.getHostName())){
				map.get(VmMemory.getHostName()).add(VmMemory);
			} else {
				List<VmMemory> l2 = new ArrayList<VmMemory>();
				l2.add(VmMemory);
				map.put(VmMemory.getHostName(), l2);
			}
		}
		//System.out.println(map);
		List<Date> x = new ArrayList<Date>(s);
		Collections.sort(x);

		//List<List<String>> y = new ArrayList<List<String>>();

		String out = "[";
		for (String s1 : map.keySet()) {
			out += "{name: '"+s1+"', data: "+getMemoryTable(map.get(s1))+"},";
		}
		out = out.substring(0, out.length()-1)+"]";

		
		return new Axis(x, out);
	}

	private String getMemoryTable(List<VmMemory> listMemory) {

		String s = "[";

		for (VmMemory m : listMemory) {
			double memUsedPerc = 0.0;
			memUsedPerc = m.getUsedMem()/m.getTotalMem()* 100;
			//s += m.getUsedMem()+",";
			s += memUsedPerc+",";
		}

		s = s.substring(0, s.length()-1) + "]";

		return s;
	}

	
	//Disk
		public Axis getVmDiskDataRead(String vmHostName , int rollupStamp) {

			List<VmDisk> l = vmDao.getVmDiskData(vmHostName ,  rollupStamp);

			Map<String, List<VmDisk>> map = new HashMap<String, List<VmDisk>>();
			Set<Date> s = new HashSet<Date>();

			for (VmDisk VmDisk : l) {
				s.add(VmDisk.getDateTime());
				if(map.containsKey(VmDisk.getHostName())){
					map.get(VmDisk.getHostName()).add(VmDisk);
				} else {
					List<VmDisk> l2 = new ArrayList<VmDisk>();
					l2.add(VmDisk);
					map.put(VmDisk.getHostName(), l2);
				}
			}
			//System.out.println(map);
			List<Date> x = new ArrayList<Date>(s);
			Collections.sort(x);

			//List<List<String>> y = new ArrayList<List<String>>();

			String out = "[";
			for (String s1 : map.keySet()) {
				out += "{name: '"+s1+"', data: "+getDiskTableRead(map.get(s1))+"},";
			}
			out = out.substring(0, out.length()-1)+"]";

			
			return new Axis(x, out);
		}

		private String getDiskTableRead(List<VmDisk> listDisk) {

			String s = "[";

			for (VmDisk d : listDisk) {
				s += d.getReads()+",";
			}

			s = s.substring(0, s.length()-1) + "]";

			return s;
		}

		public Axis getVmDiskDataWrite(String vmHostName , int rollupStamp) {

			List<VmDisk> l = vmDao.getVmDiskData(vmHostName ,  rollupStamp);

			Map<String, List<VmDisk>> map = new HashMap<String, List<VmDisk>>();
			Set<Date> s = new HashSet<Date>();

			for (VmDisk VmDisk : l) {
				s.add(VmDisk.getDateTime());
				if(map.containsKey(VmDisk.getHostName())){
					map.get(VmDisk.getHostName()).add(VmDisk);
				} else {
					List<VmDisk> l2 = new ArrayList<VmDisk>();
					l2.add(VmDisk);
					map.put(VmDisk.getHostName(), l2);
				}
			}
			//System.out.println(map);
			List<Date> x = new ArrayList<Date>(s);
			Collections.sort(x);

			//List<List<String>> y = new ArrayList<List<String>>();

			String out = "[";
			for (String s1 : map.keySet()) {
				out += "{name: '"+s1+"', data: "+getDiskTableWrite(map.get(s1))+"},";
			}
			out = out.substring(0, out.length()-1)+"]";

			
			return new Axis(x, out);
		}

		private String getDiskTableWrite(List<VmDisk> listDisk) {

			String s = "[";

			for (VmDisk d : listDisk) {
				s += d.getWrites()+",";
			}

			s = s.substring(0, s.length()-1) + "]";

			return s;
		}

		public Axis getHostCPU(String hostName , int rollupStamp) {

			List<HostInfo> l = vmDao.getHostInfo(hostName ,  rollupStamp);

			Map<String, List<HostInfo>> map = new HashMap<String, List<HostInfo>>();
			Set<Date> s = new HashSet<Date>();

			for (HostInfo hostCpu : l) {
				s.add(hostCpu.getDateTime());
				if(map.containsKey(hostCpu.getHostname())){
					map.get(hostCpu.getHostname()).add(hostCpu);
				} else {
					List<HostInfo> l2 = new ArrayList<HostInfo>();
					l2.add(hostCpu);
					map.put(hostCpu.getHostname(), l2);
				}
			}
			//System.out.println(map);
			List<Date> x = new ArrayList<Date>(s);
			Collections.sort(x);

			//List<List<String>> y = new ArrayList<List<String>>();

			String out = "[";
			for (String s1 : map.keySet()) {
				out += "{name: '"+s1+"', data: "+getHostCPUTable(map.get(s1))+"},";
			}
			out = out.substring(0, out.length()-1)+"]";

			
			return new Axis(x, out);
		}

		private String getHostCPUTable(List<HostInfo> list) {

			String s = "[";

			for (HostInfo h : list) {
				s += h.getCpuPercentage()+",";
			}

			s = s.substring(0, s.length()-1) + "]";

			return s;
		}

		
		public Axis getHostMem(String hostName , int rollupStamp) {

			List<HostInfo> l = vmDao.getHostInfo(hostName ,  rollupStamp);

			Map<String, List<HostInfo>> map = new HashMap<String, List<HostInfo>>();
			Set<Date> s = new HashSet<Date>();

			for (HostInfo hostCpu : l) {
				s.add(hostCpu.getDateTime());
				if(map.containsKey(hostCpu.getHostname())){
					map.get(hostCpu.getHostname()).add(hostCpu);
				} else {
					List<HostInfo> l2 = new ArrayList<HostInfo>();
					l2.add(hostCpu);
					map.put(hostCpu.getHostname(), l2);
				}
			}
			//System.out.println(map);
			List<Date> x = new ArrayList<Date>(s);
			Collections.sort(x);

			//List<List<String>> y = new ArrayList<List<String>>();

			String out = "[";
			for (String s1 : map.keySet()) {
				out += "{name: '"+s1+"', data: "+getHostMemTable(map.get(s1))+"},";
			}
			out = out.substring(0, out.length()-1)+"]";

			
			return new Axis(x, out);
		}

		private String getHostMemTable(List<HostInfo> list) {

			String s = "[";

			for (HostInfo h : list) {
				s += h.getMemPercentage()+",";
			}

			s = s.substring(0, s.length()-1) + "]";

			return s;
		}
		
		
		public Axis getHostNetworkTx(String hostName , int rollupStamp) {

			List<HostInfo> l = vmDao.getHostInfo(hostName ,  rollupStamp);

			Map<String, List<HostInfo>> map = new HashMap<String, List<HostInfo>>();
			Set<Date> s = new HashSet<Date>();

			for (HostInfo hostCpu : l) {
				s.add(hostCpu.getDateTime());
				if(map.containsKey(hostCpu.getHostname())){
					map.get(hostCpu.getHostname()).add(hostCpu);
				} else {
					List<HostInfo> l2 = new ArrayList<HostInfo>();
					l2.add(hostCpu);
					map.put(hostCpu.getHostname(), l2);
				}
			}
			//System.out.println(map);
			List<Date> x = new ArrayList<Date>(s);
			Collections.sort(x);

			//List<List<String>> y = new ArrayList<List<String>>();

			String out = "[";
			for (String s1 : map.keySet()) {
				out += "{name: '"+s1+"', data: "+getHostNetworkTx(map.get(s1))+"},";
			}
			out = out.substring(0, out.length()-1)+"]";

			
			return new Axis(x, out);
		}

		private String getHostNetworkTx(List<HostInfo> list) {

			String s = "[";

			for (HostInfo h : list) {
				s += h.getTx()+",";
			}

			s = s.substring(0, s.length()-1) + "]";

			return s;
		}
		
		public Axis getHostNetworkRx(String hostName , int rollupStamp) {

			List<HostInfo> l = vmDao.getHostInfo(hostName ,  rollupStamp);

			Map<String, List<HostInfo>> map = new HashMap<String, List<HostInfo>>();
			Set<Date> s = new HashSet<Date>();

			for (HostInfo hostCpu : l) {
				s.add(hostCpu.getDateTime());
				if(map.containsKey(hostCpu.getHostname())){
					map.get(hostCpu.getHostname()).add(hostCpu);
				} else {
					List<HostInfo> l2 = new ArrayList<HostInfo>();
					l2.add(hostCpu);
					map.put(hostCpu.getHostname(), l2);
				}
			}
			//System.out.println(map);
			List<Date> x = new ArrayList<Date>(s);
			Collections.sort(x);

			//List<List<String>> y = new ArrayList<List<String>>();

			String out = "[";
			for (String s1 : map.keySet()) {
				out += "{name: '"+s1+"', data: "+getHostNetworkRx(map.get(s1))+"},";
			}
			out = out.substring(0, out.length()-1)+"]";

			
			return new Axis(x, out);
		}

		private String getHostNetworkRx(List<HostInfo> list) {

			String s = "[";

			for (HostInfo h : list) {
				s += h.getRx()+",";
			}

			s = s.substring(0, s.length()-1) + "]";

			return s;
		}
}
